package gameengine;

import java.awt.*;
import java.util.*;
import javax.swing.JComponent;

/**
 * Classe principal de um jogo
 * @author Victor
 */
public class GameContainer extends JComponent
{

	private final long DEFAULT_DELAY = 16; //30 FPS
	private Vector<Sprite> sprites = new Vector<Sprite>();
	private Vector<IUpdateable> updateableListeners = new Vector<IUpdateable>();
	private Dimension resolucao;
	private Timer timerUpdate = new Timer();
	private TimerTask task;
	private long _delay;

	public GameContainer()
	{
		task = new TimerTask()
		{

			@Override
			public void run()
			{
				AtualizarFilhos();
			}
		};

		SetDelay(DEFAULT_DELAY);
	}

	/**
	 * Atualiza todos os componentes que implementam IUpdateable
	 * @owner Victor
	 */
	private void AtualizarFilhos()
	{
		for (int i = 0; i < sprites.size(); i++)
		{
			Sprite sprite = sprites.get(i);
			if (sprite instanceof IUpdateable)
			{
				IUpdateable componenteAtualizavel = (IUpdateable) sprite;
				componenteAtualizavel.Atualizar(GetDelay());
			}
		}

		for (int i = 0; i < updateableListeners.size(); i++)
		{
			IUpdateable listener = updateableListeners.get(i);
			listener.Atualizar(GetDelay());
		}
		
		repaint();
	}

	/**
	 * Retorna todas as sprites do container
	 * @owner Victor
	 */
	public Object[] GetAllSprites()
	{
		return sprites.toArray();
	}

	@Override
	/**
	 * Desenha todas as sprites
	 * @author Victor
	 */
	public void paint(Graphics g)
	{
		Graphics2D graphics = (Graphics2D) g.create();

		for(int i = 0; i < sprites.size(); i++)
		{
			sprites.get(i).Draw(graphics);
		}

		g.dispose();

		super.paint(g);
	}

	public void dispose()
	{
		task.cancel();
	}

	/**
	 * Retorna o delay entre as atualizações
	 * @owner Victor
	 */
	public long GetDelay()
	{
		return _delay;
	}

	/**
	 * Seta o delay das atualizações
	 * @owner Victor
	 */
	public final void SetDelay(long delay)
	{
		_delay = delay;

		timerUpdate.scheduleAtFixedRate(task, 0, delay);
	}

	@Override
	/**
	 * Retorna o tamanho preferido da resolução do jogo
	 * @owner Victor
	 */
	public Dimension getPreferredSize()
	{
		return resolucao;
	}

	/**
	 * Adiciona uma sprite a coleção
	 * @author Victor
	 */
	public void AddSprite(Sprite sprite)
	{
		sprites.add(sprite);
	}

	/**
	 * Remove uma sprite da coleção
	 * @author Victor
	 */
	public void RemoveSprite(Sprite sprite)
	{
		sprites.remove(sprite);
	}

	/**
	 * Adiciona um listener de update no GameContainer
	 * @owner Victor
	 */
	public void AddUpdateableListener(IUpdateable listener)
	{
		updateableListeners.add(listener);
	}

	/**
	 * Remove o listener da checagem
	 * @owner Victor
	 */
	public void RemoveUpdateableListener(IUpdateable listener)
	{
		updateableListeners.remove(listener);
	}
}
